from django.shortcuts import render
from django.http.response import HttpResponse
from PIL import Image, ImageDraw, ImageFont
from MD_django.settings import *
from django.core.cache import cache
from rest_framework.views import APIView
from rest_framework.response import Response
# from .serializers import UserSerializer
import random,os,io
from md_shop.serializers import *
import re,requests,random,uuid
from django.db.models import Q
from django.contrib.auth.hashers import make_password
from . models import *
from urllib.parse import urlencode
from rest_framework_jwt.settings import api_settings
from django.db import transaction
from django.contrib.auth.backends import ModelBackend,UserModel
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.request import CommonRequest
from itsdangerous import TimedJSONWebSignatureSerializer,SignatureExpired
import random
from django.core.mail import send_mail
from .serializers import *
from rest_framework_jwt.authentication import jwt_decode_handler
#短信验证
def send_alysms(phone,sms_code):
    AK = "LTAI4FdhTDbCRthWWB7bMSw3"
    SK = "c3Tix3XTQkJoshEcIoUoO8EnlHk4UW"

    data={"code":"sms_code"}

    client = AcsClient(AK, SK, 'cn-hangzhou')

    request = CommonRequest()
    request.set_accept_format('json')
    request.set_domain('dysmsapi.aliyuncs.com')
    request.set_method('POST')
    request.set_protocol_type('https')  # https | http
    request.set_version('2017-05-25')
    request.set_action_name('SendSms')

    request.add_query_param('RegionId', "cn-hangzhou")
    request.add_query_param('PhoneNumbers', "18843833387")  # 自己现在用的手机号
    request.add_query_param('SignName', "图图")  # 短信签名的库名
    request.add_query_param('TemplateCode', "SMS_185555433")  # 这是短信模板的code
    request.add_query_param('TemplateParam',data)

    response = client.do_action(request)
    # python2:  print(response)
    print(str(response, encoding='utf-8'))
#图片验证
def generate_image_code(request, generate_image_id):
    '''
        本地图片验证码生成函数
    '''
    bgcolor = (random.randrange(20, 100), random.randrange(
        20, 100), random.randrange(20, 100))
    width = 110
    height = 40
    # 创建画面对象
    im = Image.new('RGB', (width, height), bgcolor)
    # 创建画笔对象
    draw = ImageDraw.Draw(im)
    # 调用画笔的point()函数绘制噪点
    for i in range(0, 100):
        xy = (random.randrange(0, width), random.randrange(0, height))
        fill = (random.randrange(0, 255), 255, random.randrange(0, 255))
        draw.point(xy, fill=fill)
    # 定义验证码的备选值
    str = '1234567890QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm'
    # 随机选取4个值作为验证码
    rand_str = ''
    for i in range(0, 4):
        rand_str += str[random.randrange(0, len(str))]
    # 构造字体对象

    fonts_files = os.path.join(
        FONTS_DIRS, 'SourceCodePro-Bold.ttf')
    font = ImageFont.truetype(fonts_files, 30)
    # 构造字体颜色
    fontcolor1 = (255, random.randrange(0, 255), random.randrange(0, 255))
    fontcolor2 = (255, random.randrange(0, 255), random.randrange(0, 255))
    fontcolor3 = (255, random.randrange(0, 255), random.randrange(0, 255))
    fontcolor4 = (255, random.randrange(0, 255), random.randrange(0, 255))
    # 绘制4个字
    draw.text((5, 2), rand_str[0], font=font, fill=fontcolor1)
    draw.text((25, 2), rand_str[1], font=font, fill=fontcolor2)
    draw.text((50, 2), rand_str[2], font=font, fill=fontcolor3)
    draw.text((75, 2), rand_str[3], font=font, fill=fontcolor4)
    # 释放画笔
    del draw
    # 存入缓存，用于做进一步验证，并设置超时时间为10分组
    cache.set(generate_image_id,rand_str,60*10)
    buf = io.BytesIO()
    # 将图片保存在内存中，文件类型为png
    im.save(buf, 'png')
    # 将内存中的图片数据返回给客户端，MIME类型为图片png！
    return HttpResponse(buf.getvalue(), 'image/png')
#用户注册
class UserView(APIView):
  def post(self,request):
      phone = request.data.get("phone",'')
      username = request.data.get("username",'')
      password = request.data.get("password",'')
      password1 = request.data.get("password1",'')
      if password != password1:
        data={
          "code":408,
          "msg":"两次密码不一样，请重新输入"
        }
        return Response(data,status=200)
      phone_rul = r"1[\d]{10}$"
      phone_result = re.match(phone_rul,phone)
      if password != password1:
        data={
          "code":500,
          "msg":"手机格式不正确，请重新输入"
        }
        return Response(data,status=200)
      # 生成加密密码
      pwd_hash = make_password(password)
      try:
        user = MyUser.objects.create(username=username, password=pwd_hash,phone=phone)
        print(user)
        return Response({"code":200,"msg":"命挺好，成功啦"})
      except Exception as e:
        data={
          "code":500,
          ";msg":"注册失败了，瞅啥呢，在注册一遍啊"
        }
        return Response(data,status=200)
#图片验证生成uuid
class CheckCodeView(APIView):
    def post(self,request):
        # generate_image_id = request.data.get('generate_image_id',"")
        # data_code = cache.get(generate_image_id)
        # user_code = request.data.get('user_code',"")
        # print(user_code)
        # if data_code and user_code:
        #     print(data_code,user_code)
        #     if data_code.lower() == user_code.lower():
        #         return Response({'code':200})
        # return Response({'code':201,"msg":"验证错误"})

        data = request.data
        sms_code = data["sms_code"]
        uuid_ = data["uuid_"]
        redis_code = cache.get(uuid_)
        if redis_code.lower() == sms_code.lower():
            return Response({"code":200})
        else:
            return Response({"code":500})

class UserViews(APIView):
    def post(self,request):
        serializer = UserSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=200)
        return Response(serializer.errors, status=201)
#自定义用户登录
class UserPhoneLogin(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        user = MyUser.objects.filter(Q(username=username) | Q(phone=username)).first()
        if user is not None and user.check_password((password)):
            return user

# 重新用户登录返回函数
def jwt_response_payload_handler(token, user=None, request=None):
    '''
    :param token: jwt生成的token值
    :param user: User对象
    :param request: 请求
    '''
    return {
        'token': token,
        'user': user.username,
        'userid': user.id
    }
#微博登录
class WeiBoURLView(APIView):
    def get(self,request):
        #拼接成一个微博的url给vue
        url = "https://api.weibo.com/oauth2/authorize?"
        data={
            "client_id":WEIBO_APP_KEY,
            "response_type":"code",
            "redirect_uri":WEIBO_CALLBACK_URL
        }
        #导包自动拼接
        weibo_url= url + urlencode(data)

        print(weibo_url)
        return Response({"code":200,"url":weibo_url})
#微博登录
class WeiBoCode(APIView):
    def get(self,request):
        code = request.query_params.get("code","")
        if code:
            send_url="https://api.weibo.com/oauth2/access_token"
            send_data={
                "client_id":WEIBO_APP_KEY,
                "client_secret":WEIBO_SECRET,
                "grant_type":"authorization_code",
                "code":code,
                "redirect_uri":WEIBO_CALLBACK_URL
            }
            weibo_response = requests.post(url=send_url,data=send_data).json()
            uid = weibo_response["uid"]
            try:
                uid_user = AppUid.objects.get(uid=uid)
                user = uid_user.users
                jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
                jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
                payload = jwt_payload_handler(user)  # user指的是你查询出来的用户
                token = jwt_encode_handler(payload)
                res_data={
                    "code":200,
                    "token":token,
                    "username":uid_user.users.username,
                    "id":uid_user.users.id
                }
                return Response(res_data,status=200)
            except:
                res_data={
                    "code":404,
                    "msg":"当前用户没有uid",
                    "uid":uid
                }
                return Response(res_data,status=200)
        else:
            return Response({"code":500,"msg":"未获取到weibocode"})
#同步用户信息
class BindUser(APIView):
    def post(self,request):
        username = request.data.get("username",'')
        password = request.data.get("password",'')
        phone = request.data.get("phone",'')
        uid = request.data.get("uid",'')

        #创建两个表里的数据，用事务来解决
        try:
            #声明下面的操作uong事务来操作
            with transaction.atomic():
                #创建一个还原点
                save_id = transaction.savepoint()
                try:
                    user=MyUser.objects.create(username=username,password=make_password,
                                        phone=phone)
                    user_uid = AppUid.objects.create(uid=uid,from_app="微博",users=user)
                except:
                    #回滚到远点
                    transaction.savepoint_rollback(save_id)
                finally:
                    #将事务提交
                    transaction.savepoint_commit(save_id)
                return Response({"code":200},status=200)
        except:
            return Response({"code":500},status=200)
#发送手机验证码
class SmsCode(APIView):
    def get(self,request):
        phone = request.query_params.get("phone","")
        phone_url = r"1[\d]{10}$"
        phone_result = re.match(phone_url,phone)
        if not phone_result:
            data = {
                "code":407,
                "msg":"手机号不正确，请重新填写"
            }
            return Response(data,status=200)

        code = random.randint(100000,999999)
        print(code)
        send_alysms(phone,code)

        cache.set(phone,code)

        data={
            "code":200,
            "msg":"发送成功"
        }
        return Response(data,status=200)
#手机号注册
class SmsUserView(APIView):
    def post(self,request):
        phone = request.data.get("phone","")
        password = request.data.get("password","")
        code = request.data.get("code","")
        print(code,phone,password,cache.get(phone))
        if int(code) != int(cache.get(phone)):
            data={
                "code":4005,
                "msg":"验证码错误，请重新验证"
            }
            uuid_name = str(uuid.uuid4())
            try:
                user= MyUser.objects.create(username=uuid_name,password=make_password(password),phone=phone)
                data={
                    "code":200,
                    "msg":"手机注册成功"

                }
                return Response(data,status=200)
            except:
                data = {
                    "code": 500,
                    "msg": "手机注册失败"

                }
                return Response(data, status=200)


def peter_send_email(url,send_people):
    subject ="密码找回"
    message = "感谢使用美多商城，您现在使用的是找回密码的功能，点击下面链接找回密码：%s" % url
    from_email = EMAIL_FROM
    recipient_list = [send_people]
    res = send_mail(subject,message,from_email,recipient_list)
    return res

token_ser = TimedJSONWebSignatureSerializer(SECRET_KEY,3600)
class SendUserEView(APIView):
    def get(self,request):
        email = request.query_params.get("email","")
        print(email)
        if not email:
            data={
                "code":4005,
                "msg":"邮箱缺失，请再次发送"
            }
            return Response(data,status=200)
        data={
            "email":email
        }

        #拼接一个的dajngo独一无二的url
        token = token_ser.dumps(data).decode()
        url = "http://127.0.0.1:8080/#/reset_pwd?token=%s" % token
        res = peter_send_email(url,email)
        print(res)
        return Response({"code":200,"msg":"发送成功"})

class PasswordChangeView(APIView):
    def post(self,request):
        token = request.data.get("token","")
        password = request.data.get("password","")
        password2 = request.data.get("password2","")
        print(token,password,password2)

        if not all([token,password,password2]):
            data = {
                "code":4005,
                "msg":"数据不完整，请重新输入"
            }
            return Response(data,status=200)
        if password !=password2:
            data={
                "code":4006,
                "msg":"两次密码不一致，请重新输入"
            }
            return Response(data,status=200)
        email_data = token_ser.loads(token)
        print(email_data)
        try:
            hash_pwd = make_password(password)
            MyUser.objects.filter(email=email_data["email"]).update(password=hash_pwd)

            data={
                "code":200,
                "msg":"修改成功"
            }
            return Response(data,status=200)
        except:
            return Response({"code":500,"msg":"修改失败"},status=200)
#富文本
class FuWenBen(APIView):
    def post(self,request):
        name = request.data["name"]
        price = request.data["price"]
        color = request.data["color"]
        number = request.data["number"]
        size = request.data["size"]
        version = request.data["version"]
        content = request.data["content"]
        tsj = Goods.objects.create(name=name,price=price,color=color,
                                   number=number,size=size,version=version,
                                   content=content)
        print(tsj)
        res_data={
            "code":200,
            "msg":"成功"
        }
        return Response(res_data,status=200)

    def get(self,request):
        finfo = Goods.objects.filter().last()
        data={
            "code":200,
            "data":finfo.content
        }
        return Response(data,status=200)
#第一级分类展示
class FenLeiView(APIView):
    def get(self,request):
        fenleishow = LianXi.objects.filter(p_id=None,)
        feileis = FenLeiRes(fenleishow,many=True)
        data = feileis.data
        res_data={
            "code":200,
            "data":data,
            "msg":"成功"
        }
        return Response(res_data,status=200)
#第二级分类展示
class FentowView(APIView):
    def get(self,request):
        p_id = request.query_params.get("p_id","")
        print(p_id)
        fenleishow = LianXi.objects.filter(p_id=p_id)
        feileis = FenLeiRes(fenleishow,many=True)
        data = feileis.data
        res_data={
            "code":200,
            "data":data,
            "msg":"成功"
        }
        return Response(res_data,status=200)

#产品信息详情页面展示
class GodsInfo(APIView):
    def get(self,request):
        id = request.query_params["id"]
        try:
            goodsinfo = Goods.objects.get(id=id)
            goodsser = GoodsSER(goodsinfo)
            data = goodsser.data
            return Response(data,status=200)
        except:
            data={
                "code":500
            }
            return Response(data,status=200)

#购物车添加
class CartView(APIView):
    def post(self,request):
        # print(request.META)
        #获取商品id
        goods_id = request.data["goods_id"]
        number = request.data["number"]
        #获取用户id
        token = request.META["HTTP_AUTHORIZATION"][4:]
        print(token)
        user = jwt_decode_handler(token)
        print(user)
        user_id = user["user_id"]
        print("获取到的user_id %s" % user_id)

        try:
            user = MyUser.objects.get(id=user_id)
            goods = Goods.objects.get(id=goods_id)
            Cart.objects.create(goods_id=goods,user_id=user,image_url=goods.picture,
                                name=goods.name,price=goods.price,number=number)
            return Response({"code":200,"msg":"添加购物车成功"})
        except:
            res_data={
                "code":500,
                "msg":"失败"
            }
        return Response(status=200)

    def get(selfres,request):
        ysshow =Cart.objects.all()
        strd = CartSER(ysshow,many=True)
        return Response(strd.data)

    def put(self,request):
        number = request.data["number"]
        id = request.data["id"]
        print(request.data)
        try:
            Cart.objects.filter(id=id).update(number=number)
            return Response({"code":200,"msg":"修改成功"})
        except:
            return Response({"code": 500, "msg": "修改失败"})
def get_user_id(request):
    token = request.META["HTTP_AUTHORIZATION"][4:]
    user = jwt_decode_handler(token)
    user_id = user["user_id"]
    user = MyUser.objects.get(id=user_id)
    return user



class BuyInfoView(APIView):
    def post(self,request):
        buy_list = request.data["buys_info"]
        user = get_user_id(request)
        print(user)
        username = user.username+"_goods"
        cache.set(username,buy_list)
        print(cache.get(username))
        return Response({"code":200,"msg":"存入redis成功"})
    def get(self,request):
        user = get_user_id(request)
        #获取redis里的key
        username = user.username+"_goods"
        buy_list = cache.get(username)
        #根据获取到的列表去查询购物车的信息
        try:
            goods = Cart.objects.filter(id__in=buy_list)
            buySER = CartSER(goods,many=True)
            buy_data = buySER.data
            all_money = 0
            all_number = 0
            for i in buy_data:
                all_money += i["price"] * i["number"]
                all_number += i["number"]
            res_data={
                "code":200,
                "msg":"获取数据成功",
                "data":buy_data,
                "all_money":all_money,
                "all_number":all_number
            }
            return Response(res_data,status=200)
        except:
            res_data = {
                "code": 500,
                "msg": "获取数据失败",
            }
            return Response(res_data, status=200)

class OrdersView(APIView):
    def post(self,request):
        all_money = request.data["all_money"]
        pay_method = request.data["pay_method"]
        addresses = request.data["addresses"]
        user = get_user_id(request)
        username = user.username + "_goods"

        buys_list = cache.get(username)
        order_name = uuid.uuid4()

        try:
            with transaction.atomic():
                save_id = transaction.savepoint()
                orders = Orders(price=all_money,addresses=addresses,pay_type=pay_method,
                                user_id=user,order_sn=order_name)
                try:
                    cart = Cart.objects.filter(id__in=buys_list)
                    for i in cart:
                        buy_number = i.number
                        goods = Goods.objects.select_for_update().get(id=i.goods_id.id)
                        if buy_number > goods.number:
                            data = {
                                "code":505,
                                "msg":"老子没有那么多"
                            }
                            return Response(data,status=200)
                        else:
                            goods.number -= buy_number
                            goods.save()
                            Cart.objects.filter(id=i.id).delete()
                            cache.delete(username)
                except:
                        transaction.savepoint_rollback(save_id)

                else:
                    orders.save()
                    transaction.savepoint_commit(save_id)
                    data={
                        "code":200,
                        "msg":"成功"
                    }
                    return Response(data,status=200)

        except:
            data={"code":500,"msg":"失败"}
            return Response(data,status=200)










